<template>
  <ContentWrap>
    <el-skeleton :loading="numLoading" animated :throttle="300">
      <el-row class="statistics-card" :gutter="16">
        <el-col
          v-for="(item, index) in statisticalData"
          :key="`card-${index}`"
          :xl="4"
          :lg="4"
          :md="8"
          :sm="8"
          :xs="8"
        >
          <el-card
            shadow="hover"
            class="total-sate"
          >
            <div class="bgCircle"></div>
            <div class="bgCircle1"></div>
            <div class="flex items-center ml-16px">
              <span class="text-16px">{{ item.name }}</span>
            </div>
            <div class="text-28px ml-16px fw-600">
              <AnimatedNumber
                :from="0"
                :to="thousandBitSeparator(totalSate[item.label])"
                :key="totalSate[item.label]"
                :duration="1000"
                separator=','
              />
            </div>
            <Icon icon="ep:document" :size="28" class="gw-absolute-icon" />
          </el-card>
        </el-col>
      </el-row>
    </el-skeleton>
  </ContentWrap>
  <div>
  <el-card shadow="never" class="mb-16px" v-if="showEvaluateCard">
    <el-skeleton :loading="evaluateLoading" animated>
      <div class="dataset-top w-full mb-20px">
        <div class="dataset-title title-before">模型评测结果展示</div>
        <div class="flex"  v-if="showEvaluateChart">
          <span class="mr-16px lh-32px">选择分类:</span>
          <el-select v-model="currentDataset" @change="changeDataset" style="width: 260px">
            <el-option v-for="(d, i) in datasetList" :key="i" :value="d" :label="d" />
          </el-select>
        </div>
      </div>
      <div class="w-full mt-10px mb-14px flex">
        <div class="evaluation-top">
          <div class="evaluation-item">
            <span class="evaluation-title1">评测任务:</span>
            <span class="evaluation-title2">{{ evaluateInfo.taskName }}</span>
          </div>
          <div class="evaluation-item">
            <span class="evaluation-title1">评测方式:</span>
            <span class="evaluation-title2">{{ evaluateInfo.taskType === 0 ? '单个测评' : '对比测评' }}</span>
          </div>
          <div class="evaluation-item">
            <span class="evaluation-title1">评测时间:</span>
            <span class="evaluation-title2">{{ formatDateNum(evaluateInfo.createTime) }}</span>
          </div>
          <div class="evaluation-item">
            <span class="evaluation-title1">评测模型:</span>
              <span class="evaluation-title2">{{ evaluateInfo.modelName }}</span>
          </div>
        </div>
        <div class="evaluation-button">
          <el-button @click="goDetail" type="primary" plain>查看详情</el-button>
        </div>
      </div>
    </el-skeleton>
    <el-row class="statistics-card" :gutter="16" v-if="showEvaluateChart">
      <el-col :xl="!evaluateInfo.taskType ? 12 : 16" :lg="!evaluateInfo.taskType ? 12 : 16" :md="!evaluateInfo.taskType ? 12 : 16" :sm="24" :xs="24">
        <el-skeleton :loading="evaluateLoading" animated :rows="6">
          <Echart v-if="!evaluateInfo.taskType" :options="pieOptionsData" :height="260" />
          <Echart v-else :options="lineOptionsData" :height="260" />
        </el-skeleton>
      </el-col>
      <el-col :xl="!evaluateInfo.taskType ? 12 : 8" :lg="!evaluateInfo.taskType ? 12 : 8" :md="!evaluateInfo.taskType ? 12 : 8" :sm="24" :xs="24" class="card-border">
        <el-skeleton :loading="evaluateLoading" animated :rows="6">
          <Echart :options="radarOptionsData" :height="260" />
        </el-skeleton>
      </el-col>
    </el-row>
  </el-card>
  <el-card shadow="never" class="mb-16px">
    <div class="dataset-top w-full mb-16px">
      <div class="dataset-title title-before">数据集维度概览</div>
      <div>
        <span class="mr-16px lh-32px">选择维度:</span>
        <el-cascader
          style="width: 260px"
          v-model="datasetTypePath"
          :options="datasetTypeTree"
          :props="cascaderProps"
          @change="getDatasetStat"
          :popper-options="popperOptions"
          show-all-levels
          filterable
          clearable
          :teleported="false"
        />
      </div>
    </div>
    <el-skeleton :loading="dataset1Loading" animated>
      <div class="dataset-level1">
        <div v-for="(item, index) in datasetLevel1" :key="index" :class="['dataset-level1-item', {'active': activeLevelId === item.id}]">
          <span v-show="activeLevelId !== item.id"></span>
          <span v-show="activeLevelId !== item.id"></span>
          <span v-show="activeLevelId !== item.id"></span>
          <span v-show="activeLevelId !== item.id"></span>
          <div class="dataset-level1-item-content">
            <div class="text-30px level1-text1">{{ item.value + '%' }}</div>
            <div class="text-14px level1-text2">{{ item.name }}</div>
          </div>
        </div>
      </div>
    </el-skeleton>
    <el-row class="statistics-card" :gutter="24">
      <el-col :xl="24 / datasetChartList.length" :lg="24 / datasetChartList.length" :md="24 / datasetChartList.length" :sm="24" :xs="24" v-for="(chart, index) in datasetChartList" :key="index" :class="{'card-border': index}">
        <el-skeleton :loading="datasetLoading" animated :rows="6">
          <Echart :options="datasetChartOptionData[chart.key]" :height="280" />
        </el-skeleton>
      </el-col>
    </el-row>
  </el-card>
  </div>
</template>
<script lang="ts" setup>
import { set } from 'lodash-es'
import { EChartsOption } from 'echarts'
import { pieOptions, bar1Options, bar2Options, radarOptions, lineOptions } from './echarts-data'
import { PREDEFINE_COLORS, ECHARTS_COLORS, ECHARTS_COLORS2, hexToRGB } from '@/utils/color'
import { StatApi, StatV0 } from '@/api/multiModel/stat'
import { DatasetTypeApi } from '@/api/multiModel/datasettype'
import { EvaluationTaskApi } from '@/api/multiModel/evaluationtask' 
import { handleTree, defaultProps } from '@/utils/tree'
import { getPie3D } from '@/utils/chart'
import { formatDateNum } from '@/utils/formatTime'
import { thousandBitSeparator } from '@/utils/formatter'

defineOptions({ name: 'ModelHome' })

const { t } = useI18n()
const popperOptions:any = ref({
  modifiers: [
    {
      name: 'flip',
      options: {
          fallbackPlacements: ['bottom'],
          allowedAutoPlacements: ['bottom'],
      }
    }
  ]
})
const cascaderProps  = reactive({
  ...defaultProps,
  expandTrigger: 'hover' as const,
  emitPath: true
})
const statisticalData = ref([
  { name: '评测数据集数量', icon: 'ep:document', bgc: '#FF9E27', label:'datasetNum' },
  { name: 'prompt模版数量', icon: 'ep:document', bgc: '#F5C86F', label:'promptNum' },
  { name: '接入模型数量', icon: 'ep:document', bgc: '#56B6FD', label:'modelNum' },
  { name: '评测数据集种类', icon: 'ep:document', bgc: '#17C6C0', label:'datasetTypeNum'},
  { name: '评测指标数量', icon: 'ep:document', bgc: '#B08DFE', label:'indicateNum' },
  { name: '评测模型次数', icon: 'ep:document', bgc: '#FF6A4D', label:'evaluateNum' }
])
// 获取统计数
let totalSate = reactive<StatV0>({
  datasetNum: 0,
  promptNum: 0,
  modelNum: 0,
  datasetTypeNum: 0,
  indicateNum: 0,
  evaluateNum: 0
})
// 数量 统计
const numLoading= ref(true)
const getNum = async () => {
  let data = await StatApi.getNumStat()
  totalSate = Object.assign(totalSate, data)
  numLoading.value = false
}
// chart 颜色
const assignColors = (data, listLength, color) => {
  let colors = color.concat(); // 创建color数组的副本，以防止改变原始数组
  while (data.length < listLength) {
    // 如果data数组长度小于list数组长度，则循环通过颜色数组
    data.push(colors.shift()); // 将颜色数组的第一个颜色添加到data数组的末尾并从颜色数组中移除它
    colors.push(colors.shift()); // 将颜色数组的第一个颜色移到末尾，以保持循环
  }
  return data; // 返回最终的data数组
}

// 测评 统计
interface EvaluationTaskInfo {
  taskId:number;
  taskName:string;
  taskType:number;
  modelName:string;
  createTime:string
}
const evaluateInfo = ref<EvaluationTaskInfo>({
  taskId: 0,
  taskName: '',
  taskType: 0,
  modelName: ''	,
  createTime: ''
})
const evaluateLoading = ref(true)
const datasetList:string[] = reactive([])
const currentDataset = ref('')
const showEvaluateCard = ref(true)
const showEvaluateChart = ref(true)
let evaluateChartData:any = reactive({
  pieChart: null,
  lineChart: null,
  radarChart: null
})
const getEvaluateStat = async () => {
  initEvaluateChartData()
  const data = await EvaluationTaskApi.getEvaluateStat()
  evaluateLoading.value = false
  if (data) {
    const { pieChart, lineChart, radarChart, ...params} = data
    showEvaluateCard.value = params.taskId ? true : false
    if (!showEvaluateCard.value) return
    evaluateInfo.value = params
    let convertRadarChart = {}
    radarChart.forEach(data => {
      for (let key in data) {
        datasetList.push(key)
        convertRadarChart[key] = data[key]
      }
    })
    evaluateChartData = {
      pieChart, 
      lineChart, 
      radarChart: convertRadarChart
    }
    if (datasetList.length) {
      currentDataset.value = datasetList[0]
    }
    showEvaluateChart.value = datasetList.length ? true : false
    changeDataset()
  }
}
const initEvaluateChartData = () => {
  evaluateChartData = {
    pieChart: null,
    lineChart: null,
    radarChart: null
  }
  datasetList.length = 0
  currentDataset.value = ''
}
const changeDataset = () => {
  if (evaluateInfo.value.taskType === 0 && evaluateChartData.pieChart) {
    getEvaluatePie(evaluateChartData.pieChart[currentDataset.value])
  }
  if (evaluateInfo.value.taskType === 1 && evaluateChartData.lineChart) {
    getEvaluateLine(evaluateChartData.lineChart)
  }
  if (evaluateChartData.radarChart) {
    getEvaluateRadar(evaluateChartData.radarChart[currentDataset.value])
  }
}
const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
// 单个评测--饼图
const getEvaluatePie = async (data) => {
  if (!data) return
  const color = assignColors(PREDEFINE_COLORS, data.length, PREDEFINE_COLORS)
  data.sort((a, b) => {
      return a.ydata - b.ydata
    })
  set(
    pieOptionsData,
    'legend.data',
    data.map((v) => v.xdata)
  )
  set(
    pieOptionsData,
    'color',
    color
  )
  const seriesData = data.map((v) => {
    return {
      name: v.xdata,
      value: v.ydata
    }
  })
  set(pieOptionsData, 'series[0].data', seriesData)
  set(pieOptionsData, 'series[0].name', currentDataset.value)
}
const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption
// 对比评测--折线图
const getEvaluateLine = async (datas) => {
  if (!datas) return
  // const { xdata, ydata } = datas
  let xdata:string[] = []
  let ydata:any = []
  for ( let key in datas) {
    xdata = datas[key].xdata
    ydata.push({
      name: key,
      value: datas[key].ydata
    })
  }
  set(
    lineOptionsData,
    'xAxis.data',
    xdata
  )
  let seriesData:any[] = []
  ydata.forEach((v, index) => {
    seriesData.push({
      name: v.name,
      type: 'line',
      stack: 'Total',
      showSymbol: false,
      data: v.value,
      areaStyle: {
        color: {
          type: 'linear',
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: [
            { offset: 0, color: hexToRGB(ECHARTS_COLORS[index], 0.4) },
            { offset: 1, color: hexToRGB(ECHARTS_COLORS[index], 0.2) }
          ],
          shadowColor: 'rgba(0, 0, 0, 0.1)',
          shadowBlur: 10
        }
      },
      itemStyle: {
        color: hexToRGB(ECHARTS_COLORS[index], 1),
        borderColor:hexToRGB(ECHARTS_COLORS[index], 0.01),
        borderWidth: 4
      }
    })
  })
  set(lineOptionsData, 'series', seriesData)
}
// 雷达图
const radarOptionsData = reactive<EChartsOption>(radarOptions) as EChartsOption
const getEvaluateRadar = async (data) => {
  if (!data) return
  const { xdata, ydata } = data
  set(
    radarOptionsData,
    'radar.indicator',
    xdata.map((v) => {
      return { name: v }
    })
  )
  set(radarOptionsData, 'series[0].data', [
    {
      value: ydata,
      name: currentDataset.value
    }
  ])
}

// 数据集 统计
const datasetTypeTree = ref<Tree[]>([])
let datasetTypePath:string[] = reactive([])
let datasetChartOptionData:any = reactive({})
const getDatasetType = async () => {
  const res = await DatasetTypeApi.getDatasetTypeTop3()
  datasetTypeTree.value = []
  datasetTypeTree.value.push(...handleTree(res))
  datasetTypePath = initDatasetPath(datasetTypeTree)
  getDatasetStat()
}
const initDatasetPath = (arr:any[]) => {
  let temp = []
  function forFn(arr) {
    for (let i = 0; i < arr.length; i++) {
      let item = arr[i]
      if (!i) {
        temp.push(item.id)
        if (arr[i].children?.length) {
          forFn(arr[i].children)
        }
        break
      }
    }
  }
  forFn(unref(arr))
  return temp
}
const datasetLoading = ref(true)
let datasetChartList = reactive([])
const activeLevelId = ref(0)
const getDatasetStat = async () => {
  if (!datasetTypePath.length) return
  activeLevelId.value = datasetTypePath[0] * 1
  datasetChartList.length = 0
  let params = {}
  datasetTypePath.forEach((id, index) => {
    params[`levelId${index + 1}`] = id
  })
  const data = await StatApi.getDatasetStat(params)
  datasetLoading.value = false
  if (data) {
    Object.keys(data).forEach(key => {
      if (data[key]) {
        datasetChartList.push({
          key,
          value: data[key]
        })
      }
    })

    if (!datasetChartList.length) return
    datasetChartList.forEach((chart) => {
      datasetChartFun[chart.key]()
    })
  }
}

// 数据集领域
const color:string[] = reactive()
const getLevel2PieChart = async () => {
  const data = datasetChartList[0].value
  const color = assignColors(PREDEFINE_COLORS, data.length, PREDEFINE_COLORS)
  data.sort((a, b) => {
      return a.value - b.value
  })
  data.forEach((item, index) => {
    item.itemStyle = {
      color: color[index]
    }
    item.label = {
      normal: {
        show: true,
        color: color[index],
        formatter: [
          '{b|{b}}',
          '{d|{d}%}'
        ].join('\n'), // 用\n来换行
        rich: {
          b: {
            color: '#fff',
            lineHeight: 25,
            align: 'left'
          },
          c: {
            fontSize: 22,
            color: '#fff',
            textShadowColor: '#1c90a6',
            textShadowOffsetX: 0,
            textShadowOffsetY: 2,
            textShadowBlur: 5
          },
          d: {
            color: color[index],
            align: 'left'
          }
        }
      }
    }
    item.labelLine = {
      normal: {
        lineStyle: {
          width: 1,
          color: 'rgba(255,255,255,0.7)'
        }
      }
    }
  })
  let height = datasetChartList.length > 1 ? 26 : 10
  datasetChartOptionData['level2PieChart'] = getPie3D(data, 0, 360, 32, height, 1)
  
}
const datasetLevel3Data = reactive<EChartsOption>(bar1Options) as EChartsOption
const getLevel3BarChart = async () => {
  const { xdata, ydata } = datasetChartList[1].value
  set(
    datasetLevel3Data,
    'xAxis.data',
    xdata
  )
  const dataZoomNum:number = 10
  if (xdata.length > 6) {
    set(
      datasetLevel3Data,
      'dataZoom[0].show',
      true
    )
    set(
      datasetLevel3Data,
      'dataZoom[0].end',
      100 - (100 / xdata.length) * dataZoomNum
    )
  }
  set(datasetLevel3Data, 'series', [
    {
      name: '数据集能力项',
      data: ydata,
      type: 'bar',
      label: {
        show: true,
        position: 'top'
      },
      barWidth: ydata.length > 5 ? 25 : 30,
    }
  ])
  datasetChartOptionData['level3BarChart'] = datasetLevel3Data
}
const datasetLevel4Data = reactive<EChartsOption>(bar2Options) as EChartsOption
const getLevel4BarChart = async () => {
  const { xdata, ydata } = datasetChartList[2].value
  set(
    datasetLevel4Data,
    'yAxis.data',
    xdata
  )
  const dataZoomNum:number = 10
  if (xdata.length > 6) {
    set(
      datasetLevel4Data,
      'dataZoom[0].show',
      true
    )
    set(
      datasetLevel4Data,
      'dataZoom[0].end',
      100 - (100 / xdata.length) * dataZoomNum
    )
  }
  set(datasetLevel4Data, 'series', [
    {
      name: '数据集能力项',
      data: ydata,
      type: 'bar',
      label: {
        show: true,
      },
      barWidth: ydata.length > 5 ? 20 : 25,
    }
  ])
  datasetChartOptionData['level4BarChart'] = datasetLevel4Data
}
const dataset1Loading = ref(true)
const datasetLevel1:any = ref({})
const datasetLevel1Total = ref(0)
const getLevel1DatasetStat = async () => {
  datasetLevel1.value = []
  const data = await StatApi.getLevel1DatasetStat()
  dataset1Loading.value = false
  if (data && data.pieChart) {
    const datasetLevel1Total = data.pieChart.reduce((sum, current) => sum + current.value, 0)
    data.pieChart.forEach(d => {
      let value = d.value
      if (d.value) {
        value = d.value / datasetLevel1Total * 100
        value = Math.round(value * 10) / 10
      }
      datasetLevel1.value.push({
        ...d,
        value
      })
    })
  }
  
} 

const datasetChartFun = {
  'level2PieChart': getLevel2PieChart,
  'level3BarChart': getLevel3BarChart,
  'level4BarChart': getLevel4BarChart
}

const router = useRouter() // 路由
const goDetail = () => {
  router.push({
    path: '/task/detail',
    query: {
      id: evaluateInfo.value.taskId
    }
  })
}

/** 初始化 **/
onMounted(async() => {
  Promise.all([getNum(), getDatasetType(), getLevel1DatasetStat(), getEvaluateStat()])
  // getNum()
  // getEvaluateStat()
  // getDatasetType()
  // getLevel1DatasetStat()
})
</script>
<style scoped style="scss">
.dataset-top {
  display: flex;
  justify-content: space-between;
}
.dataset-title{
  font-size: 18px;
  color: #333;
  font-weight: 700;
}
.title-before {
  position: relative;
  &::before {
    position: absolute;
    top: 3px;
    left: -20px;
    display: inline-block;
    width: 4px;
    height: 20px;
    background-color: var(--el-color-primary);
    content: '';
  }
}
.evaluation-item {
  display: flex;
  align-items: center;
  margin-right: 26px;
  .evaluation-title1 {
    color: #171717;
    font-size: 16px;
    font-weight: 600;
    margin-right: 16px;
    min-width: 42px
  }
  .evaluation-title2 {
    color: var(--el-color-primary);
    font-size: 20px;
    font-weight: 600;
  }
}
.evaluation-button {
  width: 120px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.evaluation-top {
  height: 32px;
  width: 100%;
  display: flex;
}
.evaluation-bottom {
  height: 100px;
  display: flex;
  align-items: center;
  .evaluation-item:first-child {
    width: 80%;
  };
  .icon-item {
    display: flex;
    &:last-child {
      flex: 1;
      margin-left: 56px;
    }
  }
  .evaluation-item:last-child {
    width: 20%;
  }
}
.total-sate {
  color: white;
  border-radius: 16px;
  position: relative;
  background: linear-gradient(235deg, rgba(22,143,255, 8) 0%, rgba(22,143,255, .6) 100%);
  /* height: 126px; */
  width: 100%;
  .bgCircle {
    position: absolute;
    /* width: 138px;
    height: 138px; */
    width: 100%;
    height: 80%;
    right: -15%;
    bottom: -15%;
    background-image: url('@/assets/imgs/bg-circle.png');
    background-position: center;
    background-repeat: no-repeat;
    content: '';
  }
  .bgCircle1 {
    position: absolute;
    width: 138px;
    height: 138px;
    border-radius: 50%;
    left: -30%;
    top: -70%;
    background-color: rgba(217, 217, 217, 0.16);
    mask-composite: add; /* 叠加（默认） */
    mask-composite: subtract; /* 减去，排除掉上层的区域 */
    mask-composite: intersect; /* 相交，只显示重合的地方 */
    mask-composite: exclude;
  }
  .gw-absolute-icon {
    position: absolute;
    right: 16px;
    top: 20px;
  }
}
.items-center {
  justify-content: space-between;
  align-items: flex-end;
}
.statistics-card {
  display: flex;
  justify-content: space-between;
}
.dataset-level1 {
  display: flex;
  .dataset-level1-item {
    position: relative;
    width: 124px;
    height: 70px;
    color: var(--el-color-primary);
    margin-right: 20px;
    span {
      position: absolute;
      padding: 2px;
      border-style: solid;
      border-color: var(--el-color-primary);
      background-color: #fff;
      z-index: 1;
      &:nth-child(1) {
        top: 0px;
        left: 0px;
        border-width: 2px 0 0 2px;
      }
      &:nth-child(2) {
        top: 0px;
        right: -2px;
        border-width: 2px 2px 0 0;
      }
      &:nth-child(3) {
        right: -2px;
        bottom: -2px;
        border-width: 0 2px 2px 0;
      }
      &:nth-child(4) {
        left: 0px;
        bottom: -2px;
        border-width: 0 0 2px 2px;
      }
    }
    .dataset-level1-item-content {
      position:absolute;
      top: 0;
      left: 0;
      border: 1px solid #CCEBE7;
      width:100%;
      height: 100%;
      display: flex;
      justify-content: center;
      flex-direction: column;
      align-items: center;
      /* background-color: #00BBB8; */
      z-index: 2;
      .level1-text1 {
        /* height: 40px; */
        font-weight: 600;
      }
      .level1-text2 {
        height: 22px;
        font-weight: 600;
      }
    }
    
    &.active {
      background-color: var(--el-color-primary);
      color: #fff;
    }

  }
}
.card-border {
  border-left: 1px solid #D9D9D9;
}
.total-num .el-statistic__head{
  color: #fff !important; 
}
</style>
